package com.koron.util;

import java.math.BigDecimal;

public class NumberUtils extends org.apache.commons.lang3.math.NumberUtils{


	/**
	 * 提供精确的加法运算。
	 * 
	 * @param v1
	 *            被加数
	 * @param v2
	 *            加数
	 * @return 两个参数的和
	 */
	public static double add(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.add(b2).doubleValue();
	}

	/**
	 * 提供精确的加法运算。
	 * @param values
	 * @return
	 */
	public static double add(double... values) {
		BigDecimal result = new BigDecimal(0.00);
		for (Double d : values) {
			BigDecimal b = new BigDecimal(Double.toString(d));
			result = b.add(result);
		}
		return result.doubleValue();
	}

	/**
	 * 提供精确的减法运算。
	 * 
	 * @param v1
	 *            被减数
	 * @param v2
	 *            减数
	 * @return 两个参数的差
	 */
	public static double subtract(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.subtract(b2).doubleValue();
	}
	
	public static double subtract(double... values) {
		BigDecimal result = null;
		for (Double d : values) {
			if (result == null) {
				result = new BigDecimal(Double.toString(d));
			} else {
				BigDecimal b = new BigDecimal(Double.toString(d));
				result = result.subtract(b);
			}
		}
		return result.doubleValue();
	}

	/**
	 * 提供精确的乘法运算。
	 * 
	 * @param v1
	 *            被乘数
	 * @param v2
	 *            乘数
	 * @return 两个参数的积
	 */
	public static double multiply(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.multiply(b2).doubleValue();
	}

	/**
	 * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指 定精度，以后的数字四舍五入。
	 * 
	 * @param v1
	 *            被除数
	 * @param v2
	 *            除数
	 * @param scale
	 *            表示表示需要精确到小数点以后几位。
	 * @return 两个参数的商
	 */
	public static double divide(double v1, double v2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
	}
	
	public static double divide(long v1, long v2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		BigDecimal b1 = new BigDecimal(Long.toString(v1));
		BigDecimal b2 = new BigDecimal(Long.toString(v2));
		return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 提供精确的小数位四舍五入处理。
	 * 
	 * @param v
	 *            需要四舍五入的数字
	 * @param scale
	 *            小数点后保留几位
	 * @return 四舍五入后的结果
	 */
	public static double round(double v, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		BigDecimal b = new BigDecimal(Double.toString(v));
		BigDecimal one = new BigDecimal("1");
		return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 向上取整（非四舍五入）
	 * @param v
	 * @param scale
	 * @return
	 */
	public static double roundUp(double v, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		BigDecimal b = new BigDecimal(Double.toString(v));
		return b.setScale(scale, BigDecimal.ROUND_UP).doubleValue();
	}
	
	/**
	 * 向下取整（非四舍五入）
	 * @param v
	 * @param scale
	 * @return
	 */
	public static double roundDown(double v, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		BigDecimal b = new BigDecimal(Double.toString(v));
		return b.setScale(scale, BigDecimal.ROUND_DOWN).doubleValue();
	}
	
	/**
	 * 比较两个数值大小
	 * @param d1
	 * @param d2
	 * @return
	 */
	public static int compareTo(double d1, double d2) {
		BigDecimal dc1 = new BigDecimal(Double.toString(d1));
		BigDecimal dc2 = new BigDecimal(Double.toString(d1));
		return dc1.compareTo(dc2);
	}
    /**
	 * 数字前面自动补零
	 * @param number 数字
	 * @return
	 */
	public static String geFourNumber(Long number,int count){
		return String.format("%0"+count+"d", number);
	}
	/**
	 * 重写add方法，防止null异常
	 * @param value
	 * @return
	 */

	public static BigDecimal ifNullSetZero(BigDecimal value) {
		if(value!=null) {
			return value;
		}else {
			return BigDecimal.ZERO;
		}
	}
	/**
	 * 过滤掉null的求和
	 * @param value
	 * @return
	 */
	public static BigDecimal sum(BigDecimal ...value) {
		BigDecimal result = BigDecimal.ZERO;
		for (int i = 0; i < value.length; i++) {
			result=result.add(ifNullSetZero(value[i]));
		}
		return result;
	}
}
